home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Online / x3270 / unix_files / Playback / playback.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-04-27  |  7.3 KB  |  405 lines

  1. /*
  2.  * Copyright 1994 by Paul Mattes.
  3.  *   Permission to use, copy, modify, and distribute this software and its
  4.  *   documentation for any purpose and without fee is hereby granted,
  5.  *   provided that the above copyright notice appear in all copies and that
  6.  *   both that copyright notice and this permission notice appear in
  7.  *   supporting documentation.
  8.  *
  9.  * playback file facility for x3270
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <signal.h>
  15. #include <memory.h>
  16. #include <sys/types.h>
  17. #if !defined(sco) /*[*/
  18. #include <sys/time.h>
  19. #endif /*]*/
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. #include <arpa/inet.h>
  23. #include <arpa/telnet.h>
  24. #if defined(_IBMR2) || defined(_SEQUENT_) /*[*/
  25. #include <sys/select.h>
  26. #endif /*]*/
  27.  
  28. #define PORT        4001
  29. #define BSIZE        16384
  30. #define LINEDUMP_MAX    32
  31.  
  32. int port = PORT;
  33. char *me;
  34. static enum {
  35.     NONE, WRONG, BASE,
  36.     LESS, SPACE, ZERO, X, N, SPACE2, D1, D2
  37. } pstate = NONE;
  38. static enum {
  39.     T_NONE, T_IAC
  40. } tstate = T_NONE;
  41. int fdisp = 0;
  42.  
  43. extern int optind;
  44. extern char *optarg;
  45.  
  46. void
  47. usage()
  48. {
  49.     (void) fprintf(stderr, "usage: %s [-p port] file\n", me);
  50.     exit(1);
  51. }
  52.  
  53. main(argc, argv)
  54. int argc;
  55. char *argv[];
  56. {
  57.     int c;
  58.     FILE *f;
  59.     int s;
  60.     struct sockaddr_in sin;
  61.     int one = 1;
  62.     int len;
  63.  
  64.     /* Parse command-line arguments */
  65.  
  66.     if (me = strrchr(argv[0], '/'))
  67.         me++;
  68.     else
  69.         me = argv[0];
  70.  
  71.     while ((c = getopt(argc, argv, "p:")) != -1)
  72.         switch (c) {
  73.             case 'p':
  74.             port = atoi(optarg);
  75.             break;
  76.             default:
  77.             usage();
  78.         }
  79.  
  80.     if (argc - optind != 1)
  81.         usage();
  82.  
  83.     /* Open the file. */
  84.     f = fopen(argv[optind], "r");
  85.     if (f == (FILE *)NULL) {
  86.         perror(argv[optind]);
  87.         exit(1);
  88.     }
  89.  
  90.     /* Listen on a socket. */
  91.     s = socket(PF_INET, SOCK_STREAM, 0);
  92.     if (s < 0) {
  93.         perror("socket");
  94.         exit(1);
  95.     }
  96.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
  97.         sizeof(one)) < 0) {
  98.         perror("setsockopt");
  99.         exit(1);
  100.     }
  101.     (void) memset((char *)&sin, '\0', sizeof(sin));
  102.     sin.sin_family = AF_INET;
  103.     sin.sin_addr.s_addr = htonl(INADDR_ANY);
  104.     sin.sin_port = htons(port);
  105.     if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  106.         perror("bind");
  107.         exit(1);
  108.     }
  109.     if (listen(s, 1) < 0) {
  110.         perror("listen");
  111.         exit(1);
  112.     }
  113.     (void) signal(SIGPIPE, SIG_IGN);
  114.  
  115.     /* Accept connections and process them. */
  116.  
  117.     for (;;) {
  118.         int s2;
  119.  
  120.         (void) memset((char *)&sin, '\0', sizeof(sin));
  121.         sin.sin_family = AF_INET;
  122.         len = sizeof(sin);
  123.         (void) printf("Waiting for connection.\n");
  124.         s2 = accept(s, (struct sockaddr *)&sin, &len);
  125.         if (s2 < 0) {
  126.             perror("accept");
  127.             continue;
  128.         }
  129.         (void) printf("Connection from %s:%u.\n",
  130.             inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
  131.         rewind(f);
  132.         pstate = BASE;
  133.         fdisp = 0;
  134.         process(f, s2);
  135.     }
  136. }
  137.  
  138. void
  139. trace_netdata(direction, buf, len)
  140. char *direction;
  141. unsigned char *buf;
  142. int len;
  143. {
  144.     int offset;
  145.  
  146.     for (offset = 0; offset < len; offset++) {
  147.         if (!(offset % LINEDUMP_MAX))
  148.             (void) printf("%s%s 0x%-3x ",
  149.                 (offset ? "\n" : ""), direction, offset);
  150.         (void) printf("%02x", buf[offset]);
  151.     }
  152.     (void) printf("\n");
  153. }
  154.  
  155. process(f, s)
  156. FILE *f;
  157. int s;
  158. {
  159.     char buf[BSIZE];
  160.     int prompt = 1;
  161.  
  162.     /* Loop, looking for keyboard input or emulator response. */
  163.     for (;;) {
  164.         fd_set rfds;
  165.         struct timeval t;
  166.         int ns;
  167.  
  168.         if (prompt == 1) {
  169.             (void) printf("playback> ");
  170.             (void) fflush(stdout);
  171.         }
  172.  
  173.         FD_ZERO(&rfds);
  174.         FD_SET(s, &rfds);
  175.         FD_SET(0, &rfds);
  176.         t.tv_sec = 0;
  177.         t.tv_usec = 500000;
  178.         ns = select(s+1, &rfds, (fd_set *)NULL, (fd_set *)NULL, &t);
  179.         if (ns < 0) {
  180.             perror("select");
  181.             exit(1);
  182.         }
  183.         if (ns == 0) {
  184.             prompt++;
  185.             continue;
  186.         }
  187.         if (FD_ISSET(s, &rfds)) {
  188.             int nr;
  189.  
  190.             (void) printf("\n");
  191.             nr = read(s, buf, BSIZE);
  192.             if (nr < 0) {
  193.                 perror("read");
  194.                 break;
  195.             }
  196.             if (nr == 0) {
  197.                 (void) printf("Emulator disconnected.\n");
  198.                 break;
  199.             }
  200.             trace_netdata("emul", (unsigned char *)buf, nr);
  201.             prompt = 0;
  202.         }
  203.         if (FD_ISSET(0, &rfds)) {
  204.             if (fgets(buf, BSIZE, stdin) == (char *)NULL) {
  205.                 (void) printf("\n");
  206.                 exit(0);
  207.             }
  208.             if (!strncmp(buf, "s", 1)) {        /* step line */
  209.                 if (!step(f, s, 0))
  210.                     break;
  211.             } else if (!strncmp(buf, "r", 1)) {    /* step record */
  212.                 if (!step(f, s, 1))
  213.                     break;
  214.             } else if (!strncmp(buf, "q", 1)) {    /* quit */
  215.                 exit(0);
  216.             } else if (!strncmp(buf, "d", 1)) {    /* disconnect */
  217.                 break;
  218.             } else if (buf[0] == '?') {
  219.                 (void) printf("\
  220. s: step line\n\
  221. r: step record\n\
  222. q: quit\n\
  223. d: disconnect\n\
  224. ?: help\n");
  225.             } else if (buf[0] != '\n') {        /* junk */
  226.                 (void) printf("%c?\n", buf[0]);
  227.             }
  228.             prompt = 0;
  229.         }
  230.     }
  231.  
  232.     (void) close(s);
  233.     pstate = NONE;
  234.     tstate = T_NONE;
  235.     fdisp = 0;
  236.     return;
  237. }
  238.  
  239. int
  240. step(f, s, to_eor)
  241. FILE *f;
  242. int s;
  243. int to_eor;
  244. {
  245.     int c = 0;
  246.     static int d1;
  247.     static char hexes[] = "0123456789abcdef";
  248. #    define isxd(c) strchr(hexes, c)
  249.     static int again = 0;
  250.     char obuf[BSIZE];
  251.     char *cp = obuf;
  252. #    define NO_FDISP { if (fdisp) { printf("\n"); fdisp = 0; } }
  253.  
  254.     top:
  255.     while (again || ((c = fgetc(f)) != EOF)) {
  256.         if (!again) {
  257.             if (!fdisp || c == '\n') {
  258.                 printf("\nfile ");
  259.                 fdisp = 1;
  260.             }
  261.             if (c != '\n')
  262.                 putchar(c);
  263.         }
  264.         again = 0;
  265.         switch (pstate) {
  266.             case WRONG:
  267.             if (c == '\n')
  268.                 pstate = BASE;
  269.             break;
  270.             case BASE:
  271.             if (c == '<')
  272.                 pstate = LESS;
  273.             else {
  274.                 pstate = WRONG;
  275.                 again = 1;
  276.             }
  277.             break;
  278.             case LESS:
  279.             if (c == ' ')
  280.                 pstate = SPACE;
  281.             else {
  282.                 pstate = WRONG;
  283.                 again = 1;
  284.             }
  285.             break;
  286.             case SPACE:
  287.             if (c == '0')
  288.                 pstate = ZERO;
  289.             else {
  290.                 pstate = WRONG;
  291.                 again = 1;
  292.             }
  293.             break;
  294.             case ZERO:
  295.             if (c == 'x')
  296.                 pstate = X;
  297.             else {
  298.                 pstate = WRONG;
  299.                 again = 1;
  300.             }
  301.             break;
  302.             case X:
  303.             if (isxd(c))
  304.                 pstate = N;
  305.             else {
  306.                 pstate = WRONG;
  307.                 again = 1;
  308.             }
  309.             break;
  310.             case N:
  311.             if (isxd(c))
  312.                 pstate = N;
  313.             else if (c == ' ' || c == '\t')
  314.                 pstate = SPACE2;
  315.             else {
  316.                 pstate = WRONG;
  317.                 again = 1;
  318.             }
  319.             break;
  320.             case SPACE2:
  321.             if (isxd(c)) {
  322.                 d1 = strchr(hexes, c) - hexes;
  323.                 pstate = D1;
  324.                 cp = obuf;
  325.             } else if (c == ' ' || c == '\t')
  326.                 pstate = SPACE2;
  327.             else {
  328.                 pstate = WRONG;
  329.                 again = 1;
  330.             }
  331.             break;
  332.             case D1:
  333.             if (isxd(c)) {
  334.                 int at_eor = 0;
  335.  
  336.                 *cp = ((d1*16)+(strchr(hexes,c)-hexes));
  337.                 pstate = D2;
  338.                 switch (tstate) {
  339.                     case T_NONE:
  340.                     if (*(unsigned char *)cp == IAC)
  341.                         tstate = T_IAC;
  342.                     break;
  343.                     case T_IAC:
  344.                     if (*(unsigned char *)cp == EOR &&
  345.                         to_eor)
  346.                         at_eor = 1;
  347.                     tstate = T_NONE;
  348.                     break;
  349.                 }
  350.                 cp++;
  351.                 if (at_eor || (cp - obuf >= BUFSIZ))
  352.                     goto run_it;
  353.             } else {
  354.                 NO_FDISP;
  355.                 (void) printf("Non-hex char '%c' in playback "
  356.                     "file, skipping to newline.", c);
  357.                 pstate = WRONG;
  358.                 again = 1;
  359.             }
  360.             break;
  361.             case D2:
  362.             if (isxd(c)) {
  363.                 d1 = strchr(hexes, c) - hexes;
  364.                 pstate = D1;
  365.             } else if (c == '\n') {
  366.                 pstate = BASE;
  367.                 goto run_it;
  368.             } else {
  369.                 NO_FDISP;
  370.                 (void) printf("Non-hex char '%c' in playback "
  371.                     "file, skipping to newline.", c);
  372.                 pstate = WRONG;
  373.                 again = 1;
  374.             }
  375.             break;
  376.         }
  377.     }
  378.     goto done;
  379.  
  380.     run_it:
  381.     NO_FDISP;
  382.     trace_netdata("host", (unsigned char *)obuf, cp - obuf);
  383.     if (write(s, obuf, cp - obuf) < 0) {
  384.         perror("socket write");
  385.         return 0;
  386.     }
  387.  
  388.     if (to_eor &&
  389.         (cp - obuf < 2 ||
  390.         (unsigned char)obuf[cp - obuf - 2] != IAC ||
  391.         (unsigned char)obuf[cp - obuf - 1] != EOR)) {
  392.         cp = obuf;
  393.         goto top;
  394.     }
  395.     return 1;
  396.  
  397.     done:
  398.     if (c == EOF) {
  399.         NO_FDISP;
  400.         (void) printf("Playback file EOF.\n");
  401.     }
  402.  
  403.     return 0;
  404. }
  405.